package com.fingard.dsp.bank.directbank.cmbc01;

import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.ISinglePay;
import com.fingard.dsp.bank.reqrespobj.single.*;
import com.fingard.dsp.bank.reqrespobj.single.detail.RetAtsSglDetail;
import com.fingard.dsp.basicbankdata.ebank.EBankData;
import com.fingard.net.ConnState;
import com.fingard.text.StringHelper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Set;

/**
 * 民生银行银企直联单笔支付
 */
@Component("CMBC01SinglePay")
public class CMBC01SinglePay extends CMBC01Base implements ISinglePay {
    @Override
    public RetAtsSingle d_1908_SglPay(ReqSingle p_req1908) throws Exception {
        RetAtsSingle retAts = new RetAtsSingle(p_req1908.reqHeader);

        RetAtsSglDetail tmpRetDetail;
        //民生银行其他单位或下属子公司挂靠到其他单位进行付款
        if ("1908_CostReimbGroup".equals(p_req1908.reqHeader.commandCode)) {
            tmpRetDetail = costReimbGroup(p_req1908);
        }else if ("190803".equals(p_req1908.reqHeader.commandCode) || ("1".equals(p_req1908.singleDetail.sameBnk) && "1".equals(p_req1908.singleDetail.isPrivate))) {
            tmpRetDetail = costReimbFor190803(p_req1908);
        } else if("1908_B2EVirtualAcctToEntAcct".equals(p_req1908.reqHeader.commandCode)){
            tmpRetDetail = d_1908_virtualToAcct(p_req1908);
        }else {
            tmpRetDetail = d_1908_Xfer(p_req1908);
        }

        retAts.writeRetDetail(tmpRetDetail);
        return retAts;
    }

    /**CostReimbGroup，同行对私
     *
     * @param p_req1908
     * @return
     */
    private RetAtsSglDetail costReimbGroup(ReqSingle p_req1908) {
        RetAtsSglDetail detail = new RetAtsSglDetail(p_req1908);
        try {
            CMBC01Header bankHeader = new CMBC01Header();
            bankHeader.trnCode = "CostReimbGroup";
            XmlTextWriter xmlWriter = new XmlTextWriter();
            writeCommonHeader(xmlWriter, bankHeader);
            XElement tmpXElement = new XElement("xDataBody", "");
            tmpXElement.addChild(new XElement("trnId", p_req1908.singleDetail.askNumber));
            tmpXElement.addChild(new XElement("insId", p_req1908.singleDetail.askNumber));
            tmpXElement.addChild(new XElement("acntNo", p_req1908.singleDetail.payAct));
            tmpXElement.addChild(new XElement("acntToNo", p_req1908.singleDetail.recAct));
            tmpXElement.addChild(new XElement("acntToName", p_req1908.singleDetail.recName));
            tmpXElement.addChild(new XElement("payeeAcctType", ""));
            tmpXElement.addChild(new XElement("amount", p_req1908.singleDetail.payAmount));
            String purpose = getBankConfig().getMapValueByKey("usage190801", p_req1908.singleDetail.purpose);
            //用途字段有误，返回给ATS可用选项
            if (StringHelper.isNullOrEmpty(purpose)) {
                HashMap<String, HashMap<String, String>> usageMap = getBankConfig().readHashMap("usage190801", new String[]{"key"}, new String[]{"value"});
                Set<String> keySet = usageMap.keySet();
                StringBuilder sb = new StringBuilder("用途填写有误，请按下面要求填写:" + "\t");
                for (String s : keySet) {
                    sb.append(s).append(" ");
                }
                detail.respCode = "0";
                detail.respInfo = sb.toString();
                return detail;
            }
            tmpXElement.addChild(new XElement("explain", purpose));
            tmpXElement.addChild(new XElement("certNo", ""));
            nodeAnalysis(p_req1908.singleDetail.srcXElement, tmpXElement, getCharset());
            xmlWriter.writeXElement(tmpXElement);
            //写入报文完成
            xmlWriter.writeEndDocument();
            //发送银行
            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());
            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                //解析银行返回
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRetCode = tmpBkReader.getFirstText("/CMBC/responseHeader/status/code");
                    String tmpRetMessage = tmpBkReader.getFirstText("/CMBC/responseHeader/status/message");
                    if (!StringHelper.isNullOrEmpty(tmpRetCode)) {
                        detail.respCode = "0";
                        detail.respInfo = tmpRetMessage;
                        detail.transState = tmpRetCode;
                        detail.payInfoCode = tmpRetCode;
                    } else {
                        detail.respCode = "0";
                        detail.respInfo = tmpRetMessage;
                    }
                } else {
                    detail.respCode = "0";
                    detail.respInfo = tmpSbMsg.toString();
                }
            } else if (tmpStrRet[0].equals(ConnState.FAIL)) {
                detail.respCode = "0";
                detail.respInfo = tmpStrRet[1];
                detail.transState = PaymentState.FAIL_Payment;
                detail.payInfoCode = tmpStrRet[0];
            } else {
                detail.respCode = "0";
                detail.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            detail.respCode = "0";
            detail.respInfo = e.getMessage();
            WriteBankLogLn(e);
        }
        return detail;
    }

    @Override
    public RetAtsSingleBat d_1908BAT_SglBatPay(ReqSingleBat p_req1908BAT) throws Exception {
        return null;
    }

    //虚拟账户付款处理
    private RetAtsSglDetail d_1908_virtualToAcct(ReqSingle p_req1908) throws Exception {
        RetAtsSglDetail retDetail = new RetAtsSglDetail(p_req1908);
        CMBC01Header bankHeader = new CMBC01Header();
        bankHeader.trnCode = "B2EVirtualAcctTransToEntAcct";
        XmlTextWriter xmlWriter = new XmlTextWriter();
        writeCommonHeader(xmlWriter, bankHeader);
        XElement tmpXElement = new XElement("xDataBody", "");
        tmpXElement.addChild(new XElement("trnId", p_req1908.singleDetail.askNumber));
        tmpXElement.addChild(new XElement("insId", p_req1908.singleDetail.askNumber));
        if(StringHelper.hasAnyChar(p_req1908.singleDetail.payHigherLevelAct)){
            tmpXElement.addChild(new XElement("PayerAcNo", p_req1908.singleDetail.payHigherLevelAct
                    +"-"+p_req1908.singleDetail.payAct));
        }else {
            tmpXElement.addChild(new XElement("PayerAcNo",p_req1908.singleDetail.payAct));
        }
        tmpXElement.addChild(new XElement("PayerAcName", p_req1908.singleDetail.payName));
        tmpXElement.addChild(new XElement("PayeeAcNo", p_req1908.singleDetail.recAct));
        tmpXElement.addChild(new XElement("PayeeAcName", p_req1908.singleDetail.recName));
        tmpXElement.addChild(new XElement("externBank","1".equals(p_req1908.singleDetail.sameBnk)?"0":"1"));
        if (p_req1908.singleDetail.sameBnk.equals("1")) {
            tmpXElement.addChild(new XElement("PayChannel",""));
        } else {
            String localFlag = "";
            if (p_req1908.singleDetail.isLargeAmt()) {
                localFlag = "2";
            } else if (p_req1908.singleDetail.paySpd.equals("1")) {//加急走大额
                localFlag = "2";
            } else {
                localFlag = "1";
            }
            tmpXElement.addChild(new XElement("PayChannel",localFlag));
        }
        tmpXElement.addChild(new XElement("PayeeAcType","1".equals(p_req1908.singleDetail.isPrivate)?"1":"0"));
        tmpXElement.addChild(new XElement("BankCode",p_req1908.singleDetail.cnapsCode));
        tmpXElement.addChild(new XElement("PayeeDeptName",p_req1908.singleDetail.cnapsName));
        tmpXElement.addChild(new XElement("PayerAcAddr", ""));
        tmpXElement.addChild(new XElement("Amount", p_req1908.singleDetail.payAmount));
        tmpXElement.addChild(new XElement("Usage", p_req1908.singleDetail.purpose));
        tmpXElement.addChild(new XElement("CertNo", ""));

        nodeAnalysis(p_req1908.singleDetail.srcXElement, tmpXElement, getCharset());

        xmlWriter.writeXElement(tmpXElement);
        xmlWriter.writeEndDocument();//写入报文完成
        String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());//发送银行
        if (tmpStrRet[0].length() == 0) {
            StringBuilder tmpSbMsg = new StringBuilder();
            //解析银行返回
            XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
            if (tmpBkReader != null) {
                String tmpRetCode = tmpBkReader.getFirstText("/CMBC/responseHeader/status/code");
                String tmpRetMessage = tmpBkReader.getFirstText("/CMBC/responseHeader/status/message");
                if (StringHelper.hasAnyChar(tmpRetCode)) {
                    retDetail.respCode = "0";
                    retDetail.respInfo = tmpRetMessage;
                    retDetail.transState = tmpRetCode;
                    retDetail.payInfoCode = tmpRetCode;
                    retDetail.reqSeqID = tmpBkReader.getFirstText("/CMBC/xDataBody/cash/insId");
                } else {
                    retDetail.respCode = "-1";
                    retDetail.respInfo = tmpRetMessage;
                }
            } else {
                retDetail.respCode = "-1";
                retDetail.respInfo = tmpSbMsg.toString();
            }
        } else if (tmpStrRet[0].equals(ConnState.FAIL)) {
            retDetail.respCode = "0";
            retDetail.respInfo = tmpStrRet[1];
            retDetail.reqSeqID = p_req1908.singleDetail.askNumber;
            retDetail.transState = PaymentState.FAIL_Payment;
            retDetail.payInfoCode = tmpStrRet[0];
        } else {
            retDetail.respCode = "-1";
            retDetail.respInfo = tmpStrRet[1];
        }
        return retDetail;
    }

    //190802对外支付
    private RetAtsSglDetail d_1908_Xfer(ReqSingle p_req1908) throws Exception {
        RetAtsSglDetail retDetail = new RetAtsSglDetail(p_req1908);
        CMBC01Header bankHeader = new CMBC01Header();
        bankHeader.trnCode = "Xfer";
        XmlTextWriter xmlWriter = new XmlTextWriter();
        writeCommonHeader(xmlWriter, bankHeader);
        XElement tmpXElement = new XElement("xDataBody", "");
        tmpXElement.addChild(new XElement("trnId", p_req1908.singleDetail.askNumber));
        tmpXElement.addChild(new XElement("cltcookie", p_req1908.singleDetail.abstractATS));
        tmpXElement.addChild(new XElement("insId", p_req1908.singleDetail.askNumber));
        tmpXElement.addChild(new XElement("acntNo", p_req1908.singleDetail.payAct));
        tmpXElement.addChild(new XElement("acntName", p_req1908.singleDetail.payName));
        tmpXElement.addChild(new XElement("acntToNo", p_req1908.singleDetail.recAct));
        tmpXElement.addChild(new XElement("acntToName", p_req1908.singleDetail.recName));
        String localFlag = "";
        if (p_req1908.singleDetail.sameBnk.equals("1")) {
            tmpXElement.addChild(new XElement("externBank", "0"));
            if (p_req1908.singleDetail.sameCity.equals("1")) {
                localFlag = "0";
            } else {
                localFlag = "1";
            }
        } else {
            tmpXElement.addChild(new XElement("externBank", "1"));
            if (p_req1908.singleDetail.isLargeAmt()) {
                localFlag = "3";
            } else if (p_req1908.singleDetail.paySpd.equals("1")) {//加急走大额
                localFlag = "3";
            } else {
                localFlag = "2";
            }
            if ("190805".equalsIgnoreCase(p_req1908.reqHeader.commandCode)) {
                localFlag = "5";
            }
        }
        /*
		 * <localFlag>
	汇路：0:本地；1：异地；2:小额;3大额;4:上海同城; 5:网银互联
		 * */
        tmpXElement.addChild(new XElement("localFlag", localFlag));
        if (p_req1908.singleDetail.isPrivate.equals("1")) {//<rcvCustType>收款人账户类型：1:对公；2:对私；
            tmpXElement.addChild(new XElement("rcvCustType", "2"));
        } else {
            tmpXElement.addChild(new XElement("rcvCustType", "1"));
        }

        if ("5".equalsIgnoreCase(localFlag)) {
            String[] ebankCodeName = EBankData.mappingEBankCode(p_req1908.singleDetail.recBankCode, p_req1908.singleDetail.recStandardArea);
            if (ebankCodeName != null && ebankCodeName[0].length() > 0) {
                tmpXElement.addChild(new XElement("bankCode", ebankCodeName[0]));//收款行行号
                tmpXElement.addChild(new XElement("bankName", ebankCodeName[1]));//收款行行名
            } else {
                tmpXElement.addChild(new XElement("bankCode", p_req1908.singleDetail.cnapsCode));//收款行行号
                tmpXElement.addChild(new XElement("bankName", p_req1908.singleDetail.cnapsName));//收款行行名
            }
        } else {
            tmpXElement.addChild(new XElement("bankCode", p_req1908.singleDetail.cnapsCode));
            tmpXElement.addChild(new XElement("bankName", p_req1908.singleDetail.getOppBankLocation()));
        }
        tmpXElement.addChild(new XElement("bankAddr", ""));
        tmpXElement.addChild(new XElement("areaCode", ""));
        tmpXElement.addChild(new XElement("amount", p_req1908.singleDetail.payAmount));
        tmpXElement.addChild(new XElement("explain", p_req1908.singleDetail.purpose));
        tmpXElement.addChild(new XElement("actDate", ""));

        nodeAnalysis(p_req1908.singleDetail.srcXElement, tmpXElement, getCharset());

        xmlWriter.writeXElement(tmpXElement);
        xmlWriter.writeEndDocument();//写入报文完成
        String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());//发送银行
        if (tmpStrRet[0].length() == 0) {
            StringBuilder tmpSbMsg = new StringBuilder();
            //解析银行返回
            XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
            if (tmpBkReader != null) {
                String tmpRetCode = tmpBkReader.getFirstText("/CMBC/responseHeader/status/code");
                String tmpRetMessage = tmpBkReader.getFirstText("/CMBC/responseHeader/status/message");
                if (!StringHelper.isNullOrEmpty(tmpRetCode)) {
                    retDetail.respCode = "0";
                    retDetail.respInfo = tmpRetMessage;
                    retDetail.transState = tmpRetCode;
                    retDetail.payInfoCode = tmpRetCode;
                    retDetail.reqSeqID = tmpBkReader.getFirstText("/CMBC/xDataBody/transfer/insId");
                } else {
                    retDetail.respCode = "-1";
                    retDetail.respInfo = tmpRetMessage;
                }
            } else {
                retDetail.respCode = "-1";
                retDetail.respInfo = tmpSbMsg.toString();
            }
        } else if (tmpStrRet[0].equals(ConnState.FAIL)) {
            retDetail.respCode = "0";
            retDetail.respInfo = tmpStrRet[1];
            retDetail.reqSeqID = p_req1908.singleDetail.askNumber;
            retDetail.transState = PaymentState.FAIL_Payment;
            retDetail.payInfoCode = tmpStrRet[0];
        } else {
            retDetail.respCode = "-1";
            retDetail.respInfo = tmpStrRet[1];
        }
        return retDetail;
    }

    /**
     * 单笔费用报销：CostReimb
     *
     * @param p_req1908
     * @return
     * @throws Exception
     */
    private RetAtsSglDetail costReimbFor190803(ReqSingle p_req1908) throws Exception {
        RetAtsSglDetail retDetail = new RetAtsSglDetail(p_req1908);

        CMBC01Header bankHeader = new CMBC01Header();
        bankHeader.trnCode = "CostReimb";
        XmlTextWriter xmlWriter = new XmlTextWriter();
        writeCommonHeader(xmlWriter, bankHeader);
        XElement tmpXElement = new XElement("xDataBody", "");
        tmpXElement.addChild(new XElement("trnId", p_req1908.singleDetail.askNumber));
        tmpXElement.addChild(new XElement("insId", p_req1908.singleDetail.askNumber));
        tmpXElement.addChild(new XElement("acntNo", p_req1908.singleDetail.payAct));
        tmpXElement.addChild(new XElement("acntToNo", p_req1908.singleDetail.recAct));
        tmpXElement.addChild(new XElement("acntToName", p_req1908.singleDetail.recName));
        String cardType = "1";
        if (StringHelper.hasAnyChar(p_req1908.singleDetail.cardType)) {
            if ("1".equals(p_req1908.singleDetail.cardType)) {
                cardType = "2";
            }
        }
        tmpXElement.addChild(new XElement("payeeAcctType", cardType));
        tmpXElement.addChild(new XElement("amount", p_req1908.singleDetail.payAmount));
        if (getBankConfig().getValueAsBool("isUseUsageMapping")) {
            String explain = "";
            explain = getBankConfig().getMapValueByKey("usage190801", p_req1908.singleDetail.purpose);
            if (StringHelper.isNullOrEmpty(explain)) {
                retDetail.respCode = "-1";
                retDetail.respInfo = "用途输入不正确，没有找到编码映射！";
                return retDetail;
            }
            tmpXElement.addChild(new XElement("explain", explain));
            tmpXElement.addChild(new XElement("certNo", ""));
        } else {
            String explain = getBankConfig().getMapValueByKey("usage1908", p_req1908.singleDetail.purpose);
            WriteBankLogLn("取资金用途映射(explain)值为:" + explain);
            tmpXElement.addChild(new XElement("explain", explain));
            tmpXElement.addChild(new XElement("certNo", ""));
        }
        xmlWriter.writeXElement(tmpXElement);
        xmlWriter.writeEndDocument();

        String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());

        if (tmpStrRet[0].length() == 0) {
            StringBuilder tmpSbMsg = new StringBuilder();
            XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
            if (tmpBkReader != null) {
                String tmpRetCode = tmpBkReader.getFirstText("/CMBC/responseHeader/status/code");
                String tmpRetMessage = tmpBkReader.getFirstText("/CMBC/responseHeader/status/message");
                if (!StringHelper.isNullOrEmpty(tmpRetCode)) {
                    retDetail.respCode = "0";
                    retDetail.respInfo = tmpRetMessage;
                    retDetail.transState = tmpRetCode;
                    retDetail.payInfoCode = tmpRetCode;
                } else {
                    retDetail.respCode = "-1";
                    retDetail.respInfo = tmpRetMessage;
                }
            } else {
                retDetail.respCode = "-1";
                retDetail.respInfo = tmpSbMsg.toString();
            }
        } else if (tmpStrRet[0].equals(ConnState.FAIL)) {
            retDetail.respCode = "0";
            retDetail.respInfo = tmpStrRet[1];
            retDetail.transState = PaymentState.FAIL_Payment;
            retDetail.payInfoCode = tmpStrRet[0];
        } else {
            retDetail.respCode = "-1";
            retDetail.respInfo = tmpStrRet[1];
        }

        return retDetail;
    }

    public RetAtsSingle d_1944_QrySglPay(ReqQrySingle p_req1944) throws Exception {
        RetAtsSingle retAts = new RetAtsSingle(p_req1944.reqHeader);
        RetAtsSglDetail retDetail = new RetAtsSglDetail(p_req1944);

        try {
            CMBC01Header bankHeader = new CMBC01Header();
            bankHeader.trnCode = "qryXfer";
            XmlTextWriter xmlWriter = new XmlTextWriter();
            writeCommonHeader(xmlWriter, bankHeader);
            xmlWriter.writeStartElement("xDataBody");
            xmlWriter.writeElementString("trnId", p_req1944.reqHeader.transSeqID);
            xmlWriter.writeElementClosed("cltcookie");
            xmlWriter.writeElementString("insId", p_req1944.askNumber);
            xmlWriter.writeElementClosed("svrId");
            xmlWriter.writeEndDocument();

            String[] tmpStrRet = sendToBank(xmlWriter.toXmlString());

            if (tmpStrRet[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String tmpRetCode = tmpBkReader.getFirstText("/CMBC/responseHeader/status/code");
                    String tmpRetMessage = tmpBkReader.getFirstText("/CMBC/responseHeader/status/message");
                    if (tmpRetCode.equals("0")) {
                        retDetail.respCode = "0";
                        retDetail.reqSeqID = tmpBkReader.getFirstText("/CMBC/xDataBody/insId");
                        retDetail.respInfo = tmpBkReader.getFirstText("/CMBC/xDataBody/statusId/statusErrMsg");
                        retDetail.transState = tmpBkReader.getFirstText("/CMBC/xDataBody/statusId/statusCode");
                        retDetail.payInfoCode = retDetail.respInfo;
                        String statusSeverity = tmpBkReader.getFirstText("/CMBC/xDataBody/statusId/statusSeverity");
                        if (statusSeverity.equals("W6191") && getBankConfig().getValueAsBool("specialMappingW6191") && retDetail.respInfo.equals("转账交易失败")) {
                            retDetail.transState = retDetail.transState + "+" + statusSeverity + "+" + retDetail.respInfo;
                            retDetail.payInfoCode = statusSeverity + "-" + retDetail.respInfo;
                        }
                    } else if (tmpRetCode.equals("E1602")) {
                        retDetail.respCode = "0";
                        retDetail.respInfo = tmpRetMessage;
                        retDetail.reqSeqID = tmpBkReader.getFirstText("/CMBC/xDataBody/insId");
                        retDetail.payInfoCode = tmpRetCode;
                        retDetail.transState = tmpRetCode + "+" + tmpRetMessage;
                    } else {
                        retDetail.respCode = "-1";
                        retDetail.respInfo = tmpRetMessage;
                    }
                } else {
                    retDetail.respCode = "-1";
                    retDetail.respInfo = tmpSbMsg.toString();
                }
            } else {
                retDetail.respCode = "-1";
                retDetail.respInfo = tmpStrRet[1];
            }
        } catch (Exception e) {
            retDetail.respCode = "-1";
            retDetail.respInfo = e.getMessage();
            e.printStackTrace();
        }

        retAts.writeRetDetail(retDetail);
        return retAts;
    }

    @Override
    public RetAtsSingleBat d_1944BAT_QrySglBatPay(ReqQrySingleBat p_req1944BAT) throws Exception {
        return null;
    }
}